package server.java.autoduel;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import server.java.autoduel.Cars.ChassisFactory;
import server.java.autoduel.Player.Player;
import server.java.autoduel.Player.PlayerFactory;
import server.java.autoduel.World.World;
import server.java.autoduel.World.WorldFactory;

import com.sun.sgs.app.AppContext;
import com.sun.sgs.app.AppListener;
import com.sun.sgs.app.ClientSession;
import com.sun.sgs.app.ClientSessionListener;
import com.sun.sgs.app.DataManager;
import com.sun.sgs.app.ManagedObject;
import com.sun.sgs.app.ManagedReference;

/**
 * This is a server-only class that sets up the server and accepts client
 * log-ins
 * 
 * @author Ian Axelrod
 * @author Liz Ha
 * @author Andrew Muldowney
 * @author Edward Futch
 */
public class Server implements AppListener, Serializable, ManagedObject {
	private static final long serialVersionUID = -7989365439895266468L;

	/**
	 * The {@link Logger} for this class.
	 */
	private static final Logger logger = Logger.getLogger(Server.class
			.getName());

	/**
	 * A link to our world
	 */
	private ManagedReference<World> worldRef;

	/**
	 * Global modifier for logger output setting
	 */
	public static final Level loggerLevel = Level.OFF;

	@Override
	/**
	 * Server is initialized here.
	 * @param props a set of {@code Properties} used to configure the 
	 *        runtime state of the game
	 */
	public void initialize(Properties props) {
		Server.logger.setLevel(Server.loggerLevel);
		String cd = null;
		Server.logger.info("Starting Autoduel Server for the first time...");
		Server.logger.info("Loading game data...");
		try {
			cd = new File(".").getCanonicalPath();
			Server.logger.info("Current directory is: " + cd);
		} catch (final IOException ioe) {
			Server.logger
					.severe("Unable to obtain current directory, with message: "
							+ ioe.getMessage());
			return;
		}
		try {
			WorldFactory.logger.setLevel(Server.loggerLevel);
			WorldFactory.loadWorld(cd);
			PlayerFactory.loadPlayer(cd);
			// CarFactory.loadCars(cd);
			ChassisFactory.loadChassis(cd);
		} catch (final IOException ioe) {
			Server.logger
					.severe("An error occured trying to load the game xml file: "
							+ ioe.getMessage());
			return;
		}
		Server.logger.info("Game data successfully loaded.");
		Server.logger.info("Creating default world...");
		final World world = WorldFactory.provideWorld();
		try {
			world.loadGrids(cd);
		} catch (final IOException ioe) {
			Server.logger
					.severe("An error occured trying to load the game xml file: "
							+ ioe.getMessage());
		}
		final DataManager dataManager = AppContext.getDataManager();
		dataManager.markForUpdate(this);

		this.worldRef = dataManager.createReference(world);

		Server.logger.info("World created.");
		Server.logger.info("Server started.");
	}

	@Override
	/**
	 * Called when a player logs into the server.
	 */
	public ClientSessionListener loggedIn(ClientSession session) {
		Server.logger.info("User: " + session.getName() + " has logged in.");
		final Player player = Player.loggedIn(session);

		if (player != null) {
			// add the player to the world
			player.join(this.worldRef.get());
		}

		return player;
	}
}